module oderogue.tcod.ConfigParser;

import derelict.tcod.libtcod;

public alias TCOD_value_type_t ConfigParserValueType;

public class ConfigParser
{
	private TCOD_parser_t parser;
	
	public this()
	{
		parser = TCOD_parser_new();
	}
	
	/**
	 * Use this function to create a new structure type.
	 */
	public ConfigParserStruct createStruct(string name)
	{
		return ConfigParserStruct(TCOD_parser_new_struct(parser, std.string.toStringz(name)));
	}
	
	/**
	 * Parse the given file.
	 */
	public void parse(string fileName, ConfigParserListener listener)
	{
		TCOD_parser_run(parser, std.string.toStringz(fileName), listener.data);
	}
}

public struct ConfigParserStruct
{
	private TCOD_parser_struct_t parserStruct;
	
	private this(TCOD_parser_struct_t parserStruct)
	{
		this.parserStruct = parserStruct;
	}
	
	@property
	{
		public TCOD_parser_struct_t data() { return parserStruct; }
		/**
		 * Retrieve the name of the structure type. 
		 * Warning! Do not confuse the structure type's name with the structure's name.
		 */
		public string name() { return std.conv.to!(string)(TCOD_struct_get_name(parserStruct)); }
	}
	
	/**
	 * Use this function to add a flag property to a structure type. A flag is a simplified boolean property. 
	 * It cannot be mandatory: either it's present and it's true, or it's absent and it's false.
	 */
	public void addFlag(string name)
	{
		TCOD_struct_add_flag(parserStruct, std.string.toStringz(name));
	}
	
	/**
	 * Use this function to add a standard property to a structure type.
	 */
	public void addProperty(string name, ConfigParserValueType type, bool mandatory)
	{
		TCOD_struct_add_property(parserStruct, std.string.toStringz(name), type, mandatory);
	}
	
	/**
	 * A value-list property is a string property for which we define the list of allowed values. The parser will raise 
	 * an error if the file contains an unauthorized value for this property.
	 * The first value-list property that you add to a structure type will have the TCOD_TYPE_VALUELIST00 type. 
	 * The next TCOD_TYPE_VALUELIST01. You can define up to 16 value list property for each structure type. 
	 * The last one has the type TCOD_TYPE_VALUELIST15.
	 * You must provide a value list as a NULL terminated array of strings.
	 */
	public void addValueList(string name, char **valueList, bool mandatory)
	{
		TCOD_struct_add_value_list(parserStruct, std.string.toStringz(name), valueList, mandatory);
	}
	
	/**
	 * Add a list property to a structure type.
	 */
	public void addListProperty(string name, ConfigParserValueType type, bool mandatory)
	{
		TCOD_struct_add_list_property(parserStruct, std.string.toStringz(name), type, mandatory);
	}
	
	/**
	 * A structure can contains others structures. You can tell the parser which structures are allowed inside one 
	 * structure type with this function.
	 */
	public void addStructure(ConfigParserStruct subStructure)
	{
		TCOD_struct_add_structure(parserStruct, subStructure.data);
	}
	
	/**
	 * Check if a property is mandatory.
	 */
	public bool isPropertyMandatory(string name)
	{
		return TCOD_struct_is_mandatory(parserStruct, std.string.toStringz(name));
	}
	
	/**
	 * Get the type of a property.
	 */
	public ConfigParserValueType getPropertyType(string name)
	{
		return TCOD_struct_get_type(parserStruct, std.string.toStringz(name));
	}
}

/**
 * An abstract class for implementing parser listeners.
 */
public abstract class ConfigParserListener
{
	private TCOD_parser_listener_t *listener;
	
	public this()
	{
		listener = new TCOD_parser_listener_t();
		listener.new_struct = createNewStructHandler();
		listener.new_flag = createNewFlagHandler();
		listener.new_property = createNewPropertyHandler();
		listener.end_struct = createEndStructHandler();
		listener.error = createErrorHandler();
	}
	
	public ~this()
	{
		listener = null;
	}
	
	@property
	{
		public TCOD_parser_listener_t* data() { return listener; }
	}

	public abstract bool function(TCOD_parser_struct_t, const(char)*) createNewStructHandler();
	
	public abstract bool function(const(char)*) createNewFlagHandler();
	
	public abstract bool function(const(char)*, ConfigParserValueType, TCOD_value_t) createNewPropertyHandler();
	
	public abstract bool function(TCOD_parser_struct_t, const(char)*) createEndStructHandler();
	
	public abstract void function(const(char)*) createErrorHandler();
}
